#include "BaseFunc.h"

void img_Clone(HXLBMPFILE &src, HXLBMPFILE &des)
{
	int i, j;
	des.imagew = src.imagew;	 //长度
	des.imageh = src.imageh;	 //宽度
	des.iYRGBnum = src.iYRGBnum; //位数
	if (des.iYRGBnum == 1)
	{
		//对灰度图需复制调色板
		for (i = 0; i < 256; i++)
		{
			des.palette[i] = src.palette[i];
		}
	}
	if (!des.AllocateMem())
	{
		printf("ERROR!\n");
		exit(1);
	}
	if (des.iYRGBnum == 1)
	{
		for (i = 0; i < des.imagew; i++)
			for (j = 0; j < des.imageh; j++)
				des.pDataAt(i)[j] = src.pDataAt(i)[j];
	}
	else
	{
		for (i = 0; i < des.imagew; i++)
			for (j = 0; j < des.imageh; j++)
			{
				des.pDataAt(i, 0)[j] = src.pDataAt(i, 0)[j];
				des.pDataAt(i, 1)[j] = src.pDataAt(i, 1)[j];
				des.pDataAt(i, 2)[j] = src.pDataAt(i, 2)[j];
			}
	}
}

bool writeBit(std::string &ch, const char *cFilename)
{
	int i;
	int j;
	int count = 0; //计算字符串个数
	int num;	   //存储字符需要的多少个字节
	int left;	   //字符串剩余不足8位的个数
	FILE *fp = NULL;
	char *p = NULL;

	if (NULL == (fp = fopen(cFilename, "ab+"))) //写入一个二进制文件
	{
		printf("open file error\n");
		return false;
	}

	for (i = 0; ch[i] != 0; i++)
	{
		count++; //统计字符个数
	}
	num = count / 8;
	left = count % 8;
	printf("\n字符串共有字符%d个，占%d字节\n存储成文件后，占%d字节\n\n", count, count, (left != 0 ? num + 1 : num));

	if (left == 0) //如果left为0，那么num个字节刚好能够存放，否则需要num + 1字节
	{
		p = (char *)malloc(sizeof(char) * num);
		memset(p, 0, num);
	}
	else
	{
		p = (char *)malloc(sizeof(char) * (num + 1));
		memset(p, 0, num + 1);
	}

	j = -1;
	for (i = 0; i < count; i++) //位运算，每8个字符以2进制的形式储存在一个字符中
	{
		if (i % 8 == 0)
		{
			j++;
		}
		p[j] <<= 1;
		ch[i] -= '0';  //字符转换为数字
		p[j] |= ch[i]; //按位或后赋值
	}

	if (left != 0) //如果left不为0，需要把剩余的几个位向左边靠拢
	{
		p[j] <<= 8 - left; //例如left为2，即00000011，需要左移6位变为11000000
		// fwrite(&count, sizeof(count), 1, fp);	// 头4个字节记录长度，省略
		fwrite(p, 1, num + 1, fp);
	}
	else
	{
		// fwrite(&count, sizeof(count), 1, fp);	// 头4个字节记录长度，省略
		fwrite(p, 1, num, fp);
	}

	fclose(fp);
	free(p);
	return true;
}

bool writeHeader(HXLBMPFILE &src, const char *cFilename)
{
	FILE *f;
	f = fopen(cFilename, "w+b");
	if (f == NULL)
		return false;
	BITMAPFILEHEADER fh;
	BITMAPINFOHEADER ih;
	memset(&ih, 0, sizeof(BITMAPINFOHEADER));

	fh.bfType = 0x4d42;
	fh.bfReserved1 = fh.bfReserved2 = 0;
	fh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + ((src.iYRGBnum == 1) ? 256 * sizeof(RGBQUAD) : 0);

	ih.biSize = 40;
	ih.biPlanes = 1;
	ih.biWidth = src.imagew;
	ih.biHeight = src.imageh;
	ih.biBitCount = 8 * src.iYRGBnum;

	int w4b = (src.imagew * src.iYRGBnum + 3) / 4 * 4;
	ih.biSizeImage = ih.biHeight * w4b;
	fh.bfSize = fh.bfOffBits + ih.biSizeImage;

	fwrite(&fh, sizeof(BITMAPFILEHEADER), 1, f);
	fwrite(&ih, sizeof(BITMAPINFOHEADER), 1, f);
	if (src.iYRGBnum == 1) //因为我们只处理灰度图像，所以这里会需要写入调色板
		fwrite(src.palette, sizeof(RGBQUAD), 256, f);
	fclose(f);
	return true;
}

float *pixel_count(HXLBMPFILE &src)
{
	int i, j;
	int n = src.imageh * src.imagew;
	float *p = (float *)malloc(sizeof(float) * 256);
	int count_pixel[256] = {0};
	for (i = 0; i < src.imagew; i++) //统计像素出现次数
		for (j = 0; j < src.imageh; j++)
		{
			count_pixel[src.pDataAt(i)[j]] += 1;
		}

	for (i = 0; i < 256; i++) //计算像素出现频率
	{
		p[i] = (float)count_pixel[i] / (float)n;
	}
	return p;
}

bool readHeader(HXLBMPFILE &des, const char *cFilename)
{
	FILE *f;
	if ((f = fopen(cFilename, "r+b")) == NULL)
	{
		return false;
	}
	//文件头、信息头的读取，和LoadBMPFILE函数一致
	BITMAPFILEHEADER fh;						//文件头
	BITMAPINFOHEADER ih;						//信息头
	fread(&fh, sizeof(BITMAPFILEHEADER), 1, f); //从文件中读取文件头
	if (fh.bfType != 0x4d42)					//如果不是"BM"文件，直接退出
	{
		fclose(f);
		return false;
	}
	fread(&ih, sizeof(BITMAPINFOHEADER), 1, f);		   //从文件中读取信息头
	if ((ih.biBitCount != 8) && (ih.biBitCount != 24)) //如果不是8位灰度图，或24位彩图，则退出
	{
		fclose(f);
		return false;
	}
	des.iYRGBnum = ih.biBitCount / 8; // 1为灰度图，3为彩图
	des.imagew = ih.biWidth;
	des.imageh = ih.biHeight;
	if (!des.AllocateMem()) //如果分配内存失败，退出
	{
		fclose(f);
		return false;
	}
	if (des.iYRGBnum == 1) //灰度图需要调色板
		fread(des.palette, sizeof(RGBQUAD), 256, f);
	//信息头、文件头读取完毕
	fclose(f);
	return true;
}

char *Byte2Binary(unsigned char buffer)
{
	char *s = (char *)malloc(sizeof(char) * 9); //返回字符串，记得给'\0'预留位置
	s[0] = '\0';
	unsigned char *p, ch;
	int i, j;
	p = (unsigned char *)(&buffer);
	for (i = sizeof(buffer) - 1; i >= 0; i--)
	{
		ch = *(p + i);
		for (j = 0; j < 8; j++)
		{
			if ((ch << j) & 0x80) // 0x80即128，二进制表示1000 0000，这里操作目的是取最高位
				s[j] = '1';
			else
				s[j] = '0';
		}
		s[j] = '\0';
	}
	return s;
}